﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Threading;
using Microsoft.WindowsAPICodePack.Taskbar;
using Microsoft.WindowsAPICodePack.Shell;
using System.Reflection;
using System.Runtime.InteropServices;

namespace WeatherBar
{
    public partial class Form1 : Form
    {
        // The property that determines the icon
        // to be shown for the current weather
        int IconID { get; set; }

        JumpList jumpList;
        TaskbarManager tbManager = TaskbarManager.Instance;

        // The boolean variable
        bool goingUp = false;

        int humidity = 0;

        [DllImport("shell32.dll", SetLastError = true)]
        static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex);

        /// <summary>
        /// Extract an icon from a DLL/EXE. Used to extract
        /// icons from the local embedded native resource
        /// </summary>
        /// <param name="fileName">The name of the executable/DLL</param>
        /// <param name="iconID">Icon index</param>
        /// <returns></returns>
        private Icon GetIcon(string fileName, int iconID)
        {
            Icon ico = null;
            IntPtr hc;

            if (System.IO.File.Exists(fileName))
            {
                try
                {
                    hc = ExtractIcon(this.Handle, fileName, iconID);
                    if (!hc.Equals(IntPtr.Zero))
                    {
                        ico = Icon.FromHandle(hc);
                    }
                }
                catch{}
            }


            return ico;
        }

        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Check whether it is AM or PM in a specific region
        /// to determine the weather icon (applies to some).
        /// Using the TrueKnowledge API to get the time.
        /// </summary>
        /// <param name="location">Explicit location of the city.</param>
        /// <returns></returns>
        bool isAM(string location)
        {
            bool time = true;

            XmlDocument doc = new XmlDocument();
            try
            {
                doc.Load(string.Format("https://api.trueknowledge.com/direct_answer?question=what+is+the+time+in+{0}&api_account_id=api_application&api_password=n122jb8b75oyk8qx", location));
                XmlNamespaceManager nManager = new XmlNamespaceManager(doc.NameTable);

                nManager.AddNamespace("tk", "http://www.trueknowledge.com/ns/kengine");
                XmlNode node = doc.SelectSingleNode("//tk:text_result", nManager);

                int hours = Convert.ToInt32(node.InnerText.Substring(node.InnerText.IndexOf(',') + 1, 3));
                if ((hours > 18) || (hours < 6))
                    time = false;
                else
                    time = true;
            }
            catch
            {
                time = true;
            }

            return time;
        }

        void Form1_Shown(object sender, System.EventArgs e)
        {
            jumpList = JumpList.CreateJumpList();

            // Only get conditions if there is a location set
            // API returns error value otherwise.
            if (!string.IsNullOrEmpty(Properties.Settings.Default.Location))
            {
                Conditions conditions = Weather.GetCurrentConditions(Properties.Settings.Default.Location);
                UpdateConditions(conditions);
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            while (panel1.Location.Y < 55)
            {
                panel1.Location = new Point(142, panel1.Location.Y + 6);
            }
            timer1.Enabled = false;
            goingUp = true;
            linkLabel1.Text = "Do not change";
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            panel1.Visible = true;
            if (goingUp)
            {
                timer2.Enabled = true;
            }
            else
            {
                timer1.Enabled = true;
            }
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            while (panel1.Location.Y > 0)
            {
                panel1.Location = new Point(142, panel1.Location.Y -6);
            }
            panel1.Visible = false;
            timer2.Enabled = false;
            linkLabel1.Text = "Change location";
            goingUp = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Conditions conditions = Weather.GetCurrentConditions(textBox1.Text);
            if (conditions == null)
            {
                MessageBox.Show("Cannot find location.\nPlease enter a valid ZIP code or name.", "WeatherBar", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            else
            {
                Properties.Settings.Default.Location = conditions.City;
                Properties.Settings.Default.Save();

                timer2.Enabled = true;
                label2.Text = string.Format("{0} °F ({1} °C)", conditions.TempF, conditions.TempC);

                UpdateConditions(conditions);

            }
        }

        /// <summary>
        /// The function to trigger the overall conditions update.
        /// </summary>
        /// <param name="conditions">The instance of Conditions that contains the data.</param>
        void UpdateConditions(Conditions conditions)
        {
            RefreshImage(pictureBox2, conditions);
            this.Icon = GetIcon(Assembly.GetExecutingAssembly().Location, IconID);
            label1.Text = Properties.Settings.Default.Location;

            int x = conditions.Humidity.IndexOf(':');
            string selected = conditions.Humidity.Substring(conditions.Humidity.IndexOf(':')+1, conditions.Humidity.Length - x-2);
            humidity = Convert.ToInt32(selected);
            label3.Text = string.Format ("Humidity: {0}%",humidity.ToString());

            int _humidity = (int)humidity;
            tbManager.SetProgressValue(_humidity, 100);

            if ((_humidity > 0) && (_humidity < 50))
            {
                tbManager.SetProgressState(TaskbarProgressBarState.Normal);
            }
            else if ((_humidity > 50) && (_humidity < 70))
            {
                tbManager.SetProgressState(TaskbarProgressBarState.Paused);
            }
            else
            {
                tbManager.SetProgressState(TaskbarProgressBarState.Error);
            }

            List<Conditions> forecast = Weather.GetForecast(conditions.City);
            label4.Text = forecast[0].DayOfWeek;
            label5.Text = forecast[1].DayOfWeek;
            label6.Text = forecast[2].DayOfWeek;
            label7.Text = forecast[3].DayOfWeek;

            RefreshImage(pictureBox1, forecast[0]);
            RefreshImage(pictureBox3, forecast[1]);
            RefreshImage(pictureBox4, forecast[2]);
            RefreshImage(pictureBox5, forecast[3]);

            jumpList.ClearAllUserTasks();
            AddToJumplist(forecast[0]);
            AddToJumplist(forecast[1]);
            AddToJumplist(forecast[2]);
            AddToJumplist(forecast[3]);

            Assembly assembly = Assembly.GetExecutingAssembly();
            System.Diagnostics.Debug.Print(assembly.GetName().ToString());

            UpdateTemps(label8, label9,forecast,0);
            UpdateTemps(label11, label10, forecast, 1);
            UpdateTemps(label13, label12, forecast, 2);
            UpdateTemps(label15, label14, forecast, 3);

        }

        /// <summary>
        /// Update the temperatures for the forecasted days.
        /// </summary>
        /// <param name="maxLabel">Label to show the maximum temperature.</param>
        /// <param name="minLabel">Label to show the minimum temperature.</param>
        /// <param name="forecast">The list of Conditions instances that contain the forecast.</param>
        /// <param name="itemID">The ID of the forecast day.</param>
        void UpdateTemps(Label maxLabel, Label minLabel, List<Conditions> forecast, int itemID)
        {
            maxLabel.Text = forecast[itemID].High;
            minLabel.Text = forecast[itemID].Low;
        }

        /// <summary>
        /// Add the forecast as JumpListLink
        /// (for each day)
        /// </summary>
        /// <param name="conditions">The Conditions that contains the forecast.</param>
        void AddToJumplist(Conditions conditions)
        {
            JumpListLink jll = new JumpListLink(string.Format("http://www.google.com/ig/api?weather={0}",Properties.Settings.Default.Location), string.Format("{0}  H: {1}  L: {2}", conditions.DayOfWeek, conditions.High, conditions.Low));

            string type = conditions.Condition.ToUpper();

            switch (type)
            {
                case "SCATTERED THUNDERSTORMS":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 0);
                        break;
                    }
                case "SHOWERS":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 11);
                        break;
                    }
                case "SCATTERED SHOWERS":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 11);
                        break;
                    }
                case "RAIN AND SNOW":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 42);
                        break;
                    }
                case "OVERCAST":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 26);
                        break;
                    }
                case "LIGHT SNOW":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 13);
                        break;
                    }
                case "FREEZING DRIZZLE":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 20);
                        break;
                    }
                case "CHANCE OF RAIN":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 8);
                        break;
                    }
                case "SUNNY":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 32);
                        break;
                    }
                case "CLEAR":
                    {
                        if (isAM(conditions.City))
                            jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 32);
                        else
                            jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 31);
                        break;
                    }
                case "MOSTLY SUNNY":
                    {
                        if (isAM(conditions.City))
                            jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 34);
                        else
                            jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 29);
                        break;
                    }
                case "PARTLY CLOUDY":
                    {
                        if (isAM(conditions.City))
                            jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 44);
                        else
                            jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 27);
                        break;
                    }
                case "MOSTLY CLOUDY":
                    {
                        if (isAM(conditions.City))
                            jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 28);
                        else
                            jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 27);
                        break;
                    }
                case "CHANCE OF STORM":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 23);
                        break;
                    }
                case "RAIN":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 11);
                        break;
                    }
                case "CHANCE OF SNOW":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 15);
                        break;
                    }
                case "CLOUDY":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 26);
                        break;
                    }
                case "MIST":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 20);
                        break;
                    }
                case "STORM":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 2);
                        break;
                    }
                case "THUNDERSTORM":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 3);
                        break;
                    }
                case "CHANCE OF TSTORM":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 35);
                        break;
                    }
                case "SLEET":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 25);
                        break;
                    }
                case "SNOW":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 14);
                        break;
                    }
                case "ICY":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 25);
                        break;
                    }
                case "DUST":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 21);
                        break;
                    }
                case "FOG":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 20);
                        break;
                    }
                case "SMOKE":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 19);
                        break;
                    }
                case "HAZE":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 20);
                        break;
                    }
                case "FLURRIES":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 41);
                        break;
                    }
                case "LIGHT RAIN":
                    {
                        jll.IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 11);
                        break;
                    }

            }

            jumpList.AddUserTasks(jll);
            jumpList.Refresh();
        }

        /// <summary>
        /// Refresh the weather image for the location
        /// set in the condition passed to the function.
        /// Uses local application resources.
        /// </summary>
        /// <param name="picture">The PictureBox that will contain the picture.</param>
        /// <param name="conditions">The instance of Conditions.</param>
        void RefreshImage(PictureBox picture, Conditions conditions)
        {
            string type = conditions.Condition.ToUpper();

            switch (type)
            {
                case "SCATTERED THUNDERSTORMS":
                    {
                        picture.Image = Properties.Resources._0;
                        IconID = 1;
                        break;
                    }
                case "SHOWERS":
                    {
                        picture.Image = Properties.Resources._11;
                        IconID = 42;
                        break;
                    }
                case "SCATTERED SHOWERS":
                    {
                        picture.Image = Properties.Resources._11;
                        IconID = 42;
                        break;
                    }
                case "RAIN AND SNOW":
                    {
                        picture.Image = Properties.Resources._42;
                        IconID = 42;
                        break;
                    }
                case "OVERCAST":
                    {
                        picture.Image = Properties.Resources._26;
                        IconID = 26;
                        break;
                    }
                case "LIGHT SNOW":
                    {
                        picture.Image = Properties.Resources._13;
                        IconID = 13;
                        break;
                    }
                case "FREEZING DRIZZLE":
                    {
                        picture.Image = Properties.Resources._20;
                        IconID = 20;
                        break;
                    }
                case "CHANCE OF RAIN":
                    {
                        picture.Image = Properties.Resources._8;
                        IconID = 8;
                        break;
                    }
                case "SUNNY":
                    {
                        picture.Image = Properties.Resources._32;
                        IconID = 32;
                        break;
                    }
                case "CLEAR":
                    {
                        if (isAM(conditions.City))
                        {
                            picture.Image = Properties.Resources._32;
                            IconID = 32;
                        }
                        else
                        {
                            picture.Image = Properties.Resources._31;
                            IconID = 31;
                        }
                        break;
                    }
                case "MOSTLY SUNNY":
                    {
                        if (isAM(conditions.City))
                        {
                            picture.Image = Properties.Resources._34;
                            IconID = 34;
                        }
                        else
                        {
                            picture.Image = Properties.Resources._29;
                            IconID = 29;
                        }
                        break;
                    }
                case "PARTLY CLOUDY":
                    {
                        if (isAM(conditions.City))
                        {
                            picture.Image = Properties.Resources._44;
                            IconID = 44;
                        }
                        else
                        {
                            picture.Image = Properties.Resources._27;
                            IconID = 27;
                        }
                        break;
                    }
                case "MOSTLY CLOUDY":
                    {
                        if (isAM(conditions.City))
                        {
                            picture.Image = Properties.Resources._28;
                            IconID = 28;
                        }
                        else
                        {
                            picture.Image = Properties.Resources._27;
                            IconID = 27;
                        }
                        break;
                    }
                case "CHANCE OF STORM":
                    {
                        picture.Image = Properties.Resources._23;
                        IconID = 23;
                        break;
                    }
                case "RAIN":
                    {
                        picture.Image = Properties.Resources._11;
                        IconID = 11;
                        break;
                    }
                case "CHANCE OF SNOW":
                    {
                        picture.Image = Properties.Resources._15;
                        IconID = 15;
                        break;
                    }
                case "CLOUDY":
                    {
                        picture.Image = Properties.Resources._26;
                        IconID = 26;
                        break;
                    }
                case "MIST":
                    {
                        picture.Image = Properties.Resources._20;
                        IconID = 20;
                        break;
                    }
                case "STORM":
                    {
                        picture.Image = Properties.Resources._2;
                        IconID = 2;
                        break;
                    }
                case "THUNDERSTORM":
                    {
                        picture.Image = Properties.Resources._3;
                        IconID = 3;
                        break;
                    }
                case "CHANCE OF TSTORM":
                    {
                        picture.Image = Properties.Resources._35;
                        IconID = 35;
                        break;
                    }
                case "SLEET":
                    {
                        picture.Image = Properties.Resources._25;
                        IconID = 25;
                        break;
                    }
                case "SNOW":
                    {
                        picture.Image = Properties.Resources._14;
                        IconID = 14;
                        break;
                    }
                case "ICY":
                    {
                        picture.Image = Properties.Resources._25;
                        IconID = 25;
                        break;
                    }
                case "DUST":
                    {
                        picture.Image = Properties.Resources._21;
                        IconID = 21;
                        break;
                    }
                case "FOG":
                    {
                        picture.Image = Properties.Resources._20;
                        IconID = 20;
                        break;
                    }
                case "SMOKE":
                    {
                        picture.Image = Properties.Resources._19;
                        IconID = 19;
                        break;
                    }
                case "HAZE":
                    {
                        picture.Image = Properties.Resources._20;
                        IconID = 20;
                        break;
                    }
                case "FLURRIES":
                    {
                        picture.Image = Properties.Resources._41;
                        IconID = 41;
                        break;
                    }
                case "LIGHT RAIN":
                    {
                        picture.Image = Properties.Resources._11;
                        IconID = 11;
                        break;
                    }
                default:
                    {
                        IconID = 32;
                        break;
                    }

            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            AddUSLocation add = new AddUSLocation();
            add.Owner = this;
            add.ShowDialog();
        }

        // Timer that constantly updates the conditions for the specified region.
        private void timer3_Tick(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(Properties.Settings.Default.Location))
            {
                Conditions conditions = Weather.GetCurrentConditions(Properties.Settings.Default.Location);
                UpdateConditions(conditions);
            }
        }
    }
}
